package cn.sc.summer.core.runner;

import cn.sc.summer.constant.project.ProjectConstant;
import cn.sc.summer.constant.redis.RedisConstant;
import cn.sc.summer.redis.util.NacosInstancesService;
import cn.sc.summer.redis.util.RedisHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * 类名：全局公用启动类
 *
 * @author a-xin
 * @date 2023/8/25 14:31
 */
@Slf4j
@Component
public abstract class ServerCommonRunner implements CommandLineRunner, ApplicationListener<ContextClosedEvent> {

    @Value("${project.service.start.interval:1}")
    private Long SERVICE_START_INTERVAL;

    @Override
    public void run(String... args) {
        if (!RedisHelper.hasKey(getCompleteKey())) {
            RedisHelper.set(getCompleteKey(),
                    System.currentTimeMillis(),
                    60 * SERVICE_START_INTERVAL,
                    TimeUnit.SECONDS);
            startRunComplete(args);
        }
        startRun(args);
    }

    @Override
    public void onApplicationEvent(@NonNull ContextClosedEvent event) {
        RedisHelper.del(getCompleteKey());
        if (NacosInstancesService.isLastInstance()) {
            lastDestroy(event);
        }
        destroy(event);
    }

    /**
     * 获取服务完成key
     */
    private String getCompleteKey() {
        return RedisConstant.INSTANCES_RUNNER + ProjectConstant.SERVER_NAME + NacosInstancesService.getServerNacosAddress();
    }

    /**
     * 初始化完成后执行逻辑(服务启动指定间隔内不执行)
     *
     * @param args 参数
     */
    protected abstract void startRunComplete(String... args);

    /**
     * 初始化完成后执行逻辑
     *
     * @param args 参数
     */
    protected abstract void startRun(String... args);

    /**
     * 如果该实例为最后一个实例，则执行摧毁逻辑
     *
     * @param event spring容器关闭事件信息
     */
    protected abstract void lastDestroy(@NonNull ContextClosedEvent event);

    /**
     * 默认执行的摧毁逻辑
     *
     * @param event spring容器关闭事件信息
     */
    protected abstract void destroy(@NonNull ContextClosedEvent event);

}
